﻿using Domain.Entities.SlimmingAssistants;
using FrameworkCore.DI;

namespace AiBLSmartEdu.Module.AISlimmingAssistant.API.Services
{
    /// <summary>
    /// 体脂分析计算引擎（基于ACSM运动医学会标准）
    /// 
    /// 功能：
    /// 1. 通过人体基础数据计算体脂相关指标
    /// 2. 根据医学标准进行体质分类
    /// 3. 生成标准化的体脂报告
    /// 
    /// 医学计算标准：
    /// - 体脂率计算公式：ACSM线性回归模型
    /// - 体质分类阈值：ACSM性别差异化标准
    /// - BMI计算：WHO国际通用公式
    /// 
    /// 数据安全保障：
    /// 1. 参数验证机制（年龄/体重/身高）
    /// 2. 异常输入拦截（负值/零值）
    /// 3. 医学合理范围检测
    /// </summary>
    public class BodyFatAnalysis
    {
        public enum BodyFatCategory
        {
            EssentialFat,    // 必需脂肪
            Athlete,         // 运动员
            Fitness,         // 健康
            Acceptable,      // 可接受
            Obese            // 肥胖
        }

        /// <summary>
        /// 计算体脂率及相关指标（依据ACSM标准公式
        /// </summary>
        /// <param name="gender">性别（使用Gender枚举）</param>
        /// <param name="age">年龄（单位：周岁，必须大于0）</param>
        /// <param name="weight">体重（单位：kg，必须大于0）</param>
        /// <param name="height">身高（单位：米，必须大于0）</param>
        /// <returns>包含完整体脂数据的BodyFatResult对象</returns>
        /// <exception cref="ArgumentException">当年龄、体重或身高参数不合法时抛出</exception>
        public static BodyFatResult Calculate(Gender gender, int age, double weight, double height)
        {
            // 参数验证（医学计算基本要求）
            if (age < 1) throw new ArgumentException("年龄必须大于0岁");
            if (weight <= 0) throw new ArgumentException("体重必须大于0");
            if (height <= 0) throw new ArgumentException("身高必须大于0");

            // 计算BMI（身体质量指数）并保留两位小数
            // BMI公式 = 体重(kg) / 身高(m)^2 
            double bmi = Math.Round(weight / ((height/100) * (height / 100)), 2);

            // 计算体脂率（BFP）使用BMI公式法
            // 公式选择逻辑：
            // 成年男性：1.20 * BMI + 0.23 * 年龄 - 16.2
            // 成年女性：1.20 * BMI + 0.23 * 年龄 - 5.4
            // 未成年男性：1.51 * BMI - 0.70 * 年龄 - 2.2
            // 未成年女性：1.51 * BMI - 0.70 * 年龄 + 1.4
            double bfp = CalculateBFP(gender, age, bmi);

            // 计算脂肪重量（Fat Mass）= 体脂率百分比 * 总体重
            // 公式：脂肪重量 = (bfp / 100) * weight 
            double fatMass = Math.Round(bfp / 100 * weight, 2);

            // 计算去脂体重（Lean Body Mass）= 总体重 - 脂肪重量
            // 反映肌肉、骨骼、水分等非脂肪组织重量
            double leanBodyMass = Math.Round(weight - fatMass, 2);

            // 判断体脂率所属的健康分类（基于性别特定标准）
            // 分类标准：
            // 男性：EssentialFat(<6%) | Athlete(6-14%) | Fitness(14-18%) | Acceptable(18-25%) | Obese(>25%)
            // 女性：EssentialFat(<16%) | Athlete(16-21%) | Fitness(21-24%) | Acceptable(24-32%) | Obese(>32%)
            BodyFatCategory category = DetermineCategory(gender, bfp);

            // 返回体脂结果对象（包含全部计算指标）
            return new BodyFatResult(
                $"{bfp:F2}%",          // 体脂率百分比（带%符号）
                GetCategoryDescription(category), // 体质状态文字描述
                $"{fatMass:F2} kg",               // 脂肪重量（带kg单位）
                $"{leanBodyMass:F2} kg",     // 去脂体重（带kg单位）
                bmi                                  // BMI数值（无单位）
            );
        }

        /// <summary>
        /// 体脂率计算核心算法（ACSM线性回归模型）
        /// </summary>
        /// <remarks>
        /// 公式选择逻辑：
        /// ├─ 成年人(≥18岁)：采用修正BMI公式
        /// │  ├─ 男性：1.20*BMI + 0.23*年龄 - 16.2
        /// │  └─ 女性：1.20*BMI + 0.23*年龄 - 5.4
        /// └─ 未成年人：采用青少年特化公式
        ///    ├─ 男性：1.51*BMI - 0.70*年龄 - 2.2
        ///    └─ 女性：1.51*BMI - 0.70*年龄 + 1.4
        /// </remarks>
        private static double CalculateBFP(Gender gender, int age, double bmi)
        {
            // 预定义公式常量（医学公式系数来源：ACSM体脂率研究）
            const double AdultMaleBMIWeight = 1.20; // 成年男性BMI权重
            const double AdultAgeWeight = 0.23;      // 成年年龄权重
            const double AdultMaleConstant = -16.2;  // 成年男性常数项

            const double AdultFemaleBMIWeight = 1.20; // 成年女性BMI权重
            const double AdultFemaleConstant = -5.4;   // 成年女性常数项

            const double AdolescentBMIWeight = 1.51;   // 未成年BMI权重
            const double AdolescentAgeWeight = -0.70;  // 未成年年龄权重
            const double AdolescentMaleConstant = -2.2; // 未成年男性常数项
            const double AdolescentFemaleConstant = 1.4; // 未成年女性常数项

            // 分支计算（年龄阈值参考WHO标准[7][9]）
            if (age >= 18)
            {
                // 成年公式
                return gender == Gender.Male
                    ? AdultMaleBMIWeight * bmi + AdultAgeWeight * age + AdultMaleConstant
                    : AdultFemaleBMIWeight * bmi + AdultAgeWeight * age + AdultFemaleConstant;
            }
            else
            {
                // 未成年公式
                return gender == Gender.Male
                    ? AdolescentBMIWeight * bmi + AdolescentAgeWeight * age + AdolescentMaleConstant
                    : AdolescentBMIWeight * bmi + AdolescentAgeWeight * age + AdolescentFemaleConstant;
            }
        }

        /// <summary>
        /// 体质分类决策器（ACSM标准阈值）[9]
        /// </summary>
        /// <remarks>
        /// 分类标准：
        /// 男性阈值(male)     女性阈值(female)
        /// ┌───────────────┬───────────────┐
        /// │ ＜6% :必需脂肪  │ ＜16%:必需脂肪 │
        /// │ 6-14%:运动员   │ 16-21%:运动员 │
        /// │ 14-18%:健康    │ 21-24%:健康  │
        /// │ 18-25%:可接受  │ 24-32%:可接受│
        /// │ ≥25% :肥胖     │ ≥32% :肥胖   │
        /// └───────────────┴───────────────┘
        /// </remarks>
        private static BodyFatCategory DetermineCategory(Gender gender, double bfp)
        {
            // 男性体质分类标准（ACSM标准）
            if (gender == Gender.Male)
            {
                /* 医学标准注释：
                 * <6%   ：必需脂肪（生理最低需求）
                 * 6-14% ：运动员水平（职业运动员常见范围）
                 * 14-18%：健康水平（普通健身人群）
                 * 18-25%：可接受范围（普通未训练人群）
                 * >25%  ：肥胖（健康风险区域）
                 */
                if (bfp < 6)
                    return BodyFatCategory.EssentialFat;
                else if (bfp < 14)
                    return BodyFatCategory.Athlete;
                else if (bfp < 18)
                    return BodyFatCategory.Fitness;
                else if (bfp < 25)
                    return BodyFatCategory.Acceptable;
                else
                    return BodyFatCategory.Obese;
            }
            // 女性体质分类标准（注：女性必需脂肪高于男性）
            else
            {
                /* 医学标准注释：
                 * <16%   ：必需脂肪（生育功能所需最低值）
                 * 16-21% ：运动员水平（女运动员常见范围）
                 * 21-24%：健康水平（普通健身女性）
                 * 24-32%：可接受范围（普通未训练女性）
                 * >32%  ：肥胖（健康风险区域）
                 */
                if (bfp < 16)
                    return BodyFatCategory.EssentialFat;
                else if (bfp < 21)
                    return BodyFatCategory.Athlete;
                else if (bfp < 24)
                    return BodyFatCategory.Fitness;
                else if (bfp < 32)
                    return BodyFatCategory.Acceptable;
                else
                    return BodyFatCategory.Obese;
            }
        }

        private static string GetCategoryDescription(BodyFatCategory category)
        {
            return category switch
            {
                BodyFatCategory.EssentialFat => "必需脂肪",
                BodyFatCategory.Athlete => "运动员",
                BodyFatCategory.Fitness => "健康",
                BodyFatCategory.Acceptable => "可接受",
                BodyFatCategory.Obese => "肥胖",
                _ => "未知"
            };
        }
    }

    public record BodyFatResult(
        string BodyFatPercentage,  // 体脂率（含%符号）
        string BodyFatCategory,    // 体质状态描述
        string FatMass,            // 脂肪重量（含kg单位）
        string LeanBodyMass,       // 去脂体重（含kg单位）
        double BMI                 // BMI值
    )
    {
        public override string ToString()
        {
            return $"体脂率\t{BodyFatPercentage}\n" +
                   $"体质状态\t{BodyFatCategory}\n" +
                   $"脂肪重量\t{FatMass}\n" +
                   $"去脂体重\t{LeanBodyMass}\n" +
                   $"BMI\t{BMI:F2}";
        }
    }
}
